/**
 * Copyright (c) 2006-2007 Berlin Brown and botnode.com/Berlin Research All
 * Rights Reserved
 * 
 * http://www.opensource.org/licenses/bsd-license.php
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer. * Redistributions in binary
 * form must reproduce the above copyright notice, this list of conditions and
 * the following disclaimer in the documentation and/or other materials provided
 * with the distribution. * Neither the name of the Botnode.com (Berlin Brown)
 * nor the names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Date: 12/15/2009
 * 
 * Home Page: http://botnode.com/
 * 
 * Contact: Berlin Brown <berlin dot brown at gmail.com>
 */
package org.bresearch.octane.browse.lib;

import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import org.bresearch.octane.browse.utils.SwingWorker;
import org.bresearch.octane.net.ConnectHistory;
import org.bresearch.octane.net.ConnectResult;
import org.bresearch.octane.net.ConnectSettingsBean;
import org.bresearch.octane.net.HistoryNode;
import org.bresearch.octane.net.HttpConnect;
import org.bresearch.octane.net.IHttpConnect;
import org.bresearch.octane.net.SystemSettingsBean;
import org.bresearch.octane.parse.ParseHtml;
import org.bresearch.octane.parse.html.HtmlLink;
import org.bresearch.octane.parse.html.RenderBasicHtml;

public class BrowserHandler {

    private ConnectHistory history = new ConnectHistory();

    private IHttpConnect connection = new HttpConnect(null, null);

    private JTextField urlField;

    private JTextArea responseArea;

    private JTextField commandField;

    private JTextField statusArea;

    /**
     * Constructor for ConnectFrame.
     * 
     * @param url
     *            JTextField
     * @param response
     *            JTextArea
     * @param actionButton
     *            JButton
     */
    public BrowserHandler(final JTextField url, final JTextArea response, final JTextField command, final JTextField statusArea) {

        this.urlField = url;
        this.responseArea = response;
        this.commandField = command;
        this.statusArea = statusArea;
    }

    // ///////////////////////////////////////////////////////////////

    public SwingWorker buildCommandWorker() {
        return new HandleCommandWorker();
    }

    public SwingWorker buildConnectWorker() {
        return new HandleConnectWorker();
    }
    
    public SwingWorker buildConnectWorkerPrev() {
        return new HandleCommandWorkerPrev();
    }

    
    public class HandleCommandWorkerPrev extends SwingWorker {

        public Object construct() {
            BrowserHandler.this.handleConnectPrev();
            return "" + Thread.currentThread();
        }
    }

    
    public class HandleCommandWorker extends SwingWorker {

        public Object construct() {
            BrowserHandler.this.handleCommand(BrowserHandler.this.commandField.getText());
            return "" + Thread.currentThread();
        }
    }

    public class HandleConnectWorker extends SwingWorker {

        private long tstart = 0;

        private long tend;

        private long tdiff;

        public Object construct() {
            BrowserHandler.this.handleConnect();
            return "" + Thread.currentThread();
        }

        public void start() {
            this.tstart = System.currentTimeMillis();
            System.out.println("Executing...");
            super.start();
        }

        public void execTime() {
            this.tend = System.currentTimeMillis();
            this.tdiff = this.tend - tstart;
        }

        public void finished() {

            System.out.println("Operation complete [!]");
            this.execTime();
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    BrowserHandler.this.statusArea.setText("Operation complete in " + tdiff + " ms");
                }
            });

            super.finished();
        }

    } // End of the Class //

    public void parseAndConnect(final int inputLinkId) {

        final ParseHtml parser = this.connection.getParser();
        final HtmlLink link = parser.getHtmlLink(inputLinkId);
        if (link != null) {

            // Attempt another connect //
            System.out.println("Attempting connect to link : " + link.getHrefLink());
            this.urlField.setText(link.getHrefLink());
            this.handleConnect();

        } else {
            System.out.println("Invalid link id : " + inputLinkId);
        } // End of the if - else //

    }

    /**
     * Connect to the previously connected URL address.
     * 
     * @return
     */
    public ConnectSettingsBean prevHistoryLink() {

        // Use the history
        if (this.history.getHistoryPointer() != null) {
            final HistoryNode historyNode = this.history.getHistoryPointer();
            return historyNode.next();
        } else {
            System.out.println("No history object");
        } // End of the if - else //
        return null;

    }

    /**
     * Connect to the previously connected URL address.
     * 
     * @return
     */
    public void connectPrevHistory() {

        final ConnectSettingsBean prevConnect = this.prevHistoryLink();
        if (prevConnect != null) {

            final SystemSettingsBean proxySettings = new SystemSettingsBean(SystemSettingsBean.USER_AGENT, false, "proxy", 9999);
            final ConnectSettingsBean connectSettings = new ConnectSettingsBean(prevConnect.getUrl());
            this.connect(proxySettings, connectSettings);

            // Display connect prev message
            System.out.println("Connecting to previous URL request, url=" + prevConnect.getUrl());
            final StringBuilder buf = new StringBuilder(100);
            buf.append(connection.getLastResult().buildHeaderResponse());
            buf.append(">>>>-------------------\n");

            final ConnectResult result = connection.getLastResult();
            final RenderBasicHtml renderHtml = result.getRenderHtml();
            buf.append(renderHtml.getRenderHtmlData());
            this.responseArea.setText(buf.toString());

        } // End of the if //
    }

    public void handleConnectPrev() {
     // Convert to integer, use as the link id //
        try {            
            final ConnectResult result = connection.getLastResult();
            if (result != null) {       
                    connectPrevHistory();
            } else {
                System.out.println("No html results from previous request");
            } // End of the if - else //

        } catch (NumberFormatException e) {
            e.printStackTrace();
        } // End of the try - catch //
        
    }
    
    public void handleCommand(final String text) {

        // Convert to integer, use as the link id //
        try {
            final int inputLinkId = Integer.parseInt(text);
            System.out.println("Processing command link Id : " + inputLinkId);
            final ConnectResult result = connection.getLastResult();
            if (result != null) {

                // First check if the link id is negative //
                if (inputLinkId == -1) {
                    connectPrevHistory();
                } else {
                    this.parseAndConnect(inputLinkId);
                } // End of the if - else //

            } else {
                System.out.println("No html results from previous request");
            } // End of the if - else //

        } catch (NumberFormatException e) {
            e.printStackTrace();
        } // End of the try - catch //
        
    }

    public void connect(final SystemSettingsBean proxySettings, final ConnectSettingsBean connectSettings) {

        this.connection = new HttpConnect(connectSettings, proxySettings);
        connection.buildConnectProperties();
        connection.connect(connection.buildURL());
        connection.parse();
    }

    /**
     * Connect to URL.
     */
    public void handleConnect() {

        System.out.println("Executing Connect");
        final SystemSettingsBean proxySettings = new SystemSettingsBean(SystemSettingsBean.USER_AGENT, false, "proxy", 9999);
        final ConnectSettingsBean connectSettings = new ConnectSettingsBean(this.urlField.getText());
        this.history.addConnectInfo(connectSettings);
        this.connect(proxySettings, connectSettings);

        final StringBuilder buf = new StringBuilder(100);
        buf.append(connection.getLastResult().buildHeaderResponse());
        buf.append(">>>>-------------------\n");

        final ConnectResult result = connection.getLastResult();
        final RenderBasicHtml renderHtml = result.getRenderHtml();
        buf.append(renderHtml.getRenderHtmlData());
        this.responseArea.setText(buf.toString());

    }

} // End of the Class //
